package com.haixiaoke.saas.enterprise.order.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.haixiaoke.saas.common.annotation.Log;
import com.haixiaoke.saas.common.annotation.RepeatSubmit;
import com.haixiaoke.saas.common.annotation.TenantScope;
import com.haixiaoke.saas.common.constant.OrderConstants;
import com.haixiaoke.saas.common.core.domain.AjaxResult;
import com.haixiaoke.saas.common.core.page.TableDataInfo;
import com.haixiaoke.saas.common.enums.BusinessType;
import com.haixiaoke.saas.common.enums.OrderStateEnum;
import com.haixiaoke.saas.common.exception.ServiceException;
import com.haixiaoke.saas.common.tenant.TenantContext;
import com.haixiaoke.saas.common.utils.DateUtils;
import com.haixiaoke.saas.common.utils.poi.ExcelUtil;
import com.haixiaoke.saas.contract.domain.LesseeContract;
import com.haixiaoke.saas.enterprise.contract.controller.EnterpriseLesseeContractController;
import com.haixiaoke.saas.order.domain.Order;
import com.haixiaoke.saas.order.domain.OrderStateRecord;
import com.haixiaoke.saas.order.service.IOrderService;
import com.haixiaoke.saas.order.state.server.IOrderStateServerRole;
import com.haixiaoke.saas.order.state.server.OrderStateServerRole;
import com.haixiaoke.saas.system.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 订单Controller
 *
 * @author qixi
 * @date 2024-03-04
 */
@RestController
@RequestMapping("/enterprise/order/order")
public class EnterpriseOrderController extends BaseController {
    @Autowired
    private IOrderService orderService;
    @Autowired
    private EnterpriseLesseeContractController lesseeContractController;


    /**
     * 查询订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:order:list')")
    @GetMapping("/list")
    @TenantScope
    public TableDataInfo list(Order order) {
        startPage();
        order.setTenantId(TenantContext.getTenantId());
        order.setOrderType(Order.ORDER_TYPE_LONG_LEASE);
        List<Order> list = orderService.selectOrderList(order);
        return getDataTable(list);
    }

    /**
     * 查询公寓父订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:order:list')")
    @GetMapping("/apartment/list")
    @TenantScope
    public TableDataInfo apartmentList(Order order) {
        startPage();
        order.setSearchValue("1");
        order.setTenantId(TenantContext.getTenantId());
        List<Order> list = orderService.selectApartmentOrderList(order);
        return getDataTable(list);
    }

    /**
     * 查询公寓续租订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:order:list')")
    @GetMapping("/apartment/relet/list")
    @TenantScope
    public TableDataInfo apartmentReletList(Order order) {
        startPage();
        order.setSearchValue("2");
        order.setTenantId(TenantContext.getTenantId());
        List<Order> list = orderService.selectApartmentOrderList(order);
        return getDataTable(list);
    }

    /**
     * 查询有效订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:order:validList')")
    @GetMapping("/validList")
    @TenantScope
    public TableDataInfo validList(Order order) {
        startPage();
        order.setTenantId(TenantContext.getTenantId());
        List<Order> list = orderService.selectOrderValidList(order);
        return getDataTable(list);
    }

    /**
     * 查询房屋租赁时间列表
     */
    @GetMapping("/rentList/{houseId}")
    public AjaxResult selectRentTimeList(@PathVariable String houseId) {
        if (StrUtil.isBlank(houseId)) {
            return success();
        }
        return success(orderService.selectRentTimeList(houseId));
    }


    /**
     * 导出订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:order:export')")
    @Log(title = "订单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Order order) {
        List<Order> list = orderService.selectOrderList(order);
        ExcelUtil<Order> util = new ExcelUtil<Order>(Order.class);
        util.exportExcel(response, list, "订单数据");
    }

    /**
     * 获取订单详细信息
     */
    @PreAuthorize("@ss.hasPermi('order:order:query')")
    @GetMapping(value = "/{orderId}")
    public AjaxResult getInfo(@PathVariable("orderId") String orderId) {
        return success(orderService.selectOrderByOrderId(orderId));
    }

    /**
     * 获取订单详细信息
     */
    @PreAuthorize("@ss.hasPermi('order:order:query')")
    @GetMapping(value = "/apartment/{orderId}")
    public AjaxResult apartmentGetInfo(@PathVariable("orderId") String orderId) {
        return success(orderService.selectApartmentOrderByOrderId(orderId));
    }

    /**
     * 房态获取订单详细信息
     */
    @PreAuthorize("@ss.hasPermi('order:order:query')")
    @GetMapping(value = "/houseDynamic/{orderId}")
    public AjaxResult houseDynamicGetInfo(@PathVariable("orderId") String orderId) {
        return success(orderService.selectHouseDynamicOrderByOrderId(orderId));
    }

    /**
     * 新增预定订单
     */
    @PreAuthorize("@ss.hasPermi('order:order:add')")
    @Log(title = "订单", businessType = BusinessType.INSERT)
    @PostMapping
    @TenantScope
    @RepeatSubmit
    public AjaxResult add(@RequestBody @Valid Order order) {
        order.setTenantId(TenantContext.getTenantId());
        if (orderService.checkRepeatOrder(order)) {
            throw new ServiceException("房间在入住时间内已出租");
        }
        String today = DateUtil.today();
        if (order.getCheckInTime().getTime() < DateUtil.parse(today).getTime() || order.getCheckOutTime().getTime() < DateUtil.parse(today).getTime()) {
            throw new ServiceException("租住周期不能早于当前时间");
        }
        return toAjax(ObjectUtil.isEmpty(orderService.insertPreOrder(order)) ? 0 : 1);
    }

    /**
     * 修改订单
     */
    @PutMapping
    public AjaxResult edit(@RequestBody Order order) {
        return toAjax(orderService.updateOrder(order));
    }


    /**
     * 删除订单
     */
    @PreAuthorize("@ss.hasPermi('order:order:remove')")
    @Log(title = "订单", businessType = BusinessType.DELETE)
    @DeleteMapping("/{orderIds}")
    public AjaxResult remove(@PathVariable String[] orderIds) {
        return toAjax(orderService.deleteOrderByOrderIds(orderIds));
    }


    // IOrderStateServerRole stateServerRole = new OrderStateServerRole(order);
    //     stateServerRole.p();


    /**
     * 订单签约
     */
    @PostMapping("/sign")
    @TenantScope
    @RepeatSubmit
    public AjaxResult sign(@RequestBody @Valid LesseeContract lesseeContract) {
        lesseeContract.setTenantId(TenantContext.getTenantId());
        AjaxResult ajaxResult = lesseeContractController.checkContractParams(lesseeContract);
        if (ajaxResult != null) {
            return ajaxResult;
        }
        lesseeContract.setCreateBy(getUsername());
        return toAjax(orderService.signOrder(lesseeContract));
    }

    /**
     * 预定变更
     */
    @PostMapping("/changeOrder")
    @TenantScope
    public AjaxResult changeOrder(@RequestBody Order order) {
        Order orderByOrderId = orderService.selectOrderByOrderId(order.getOrderId());
        if (orderByOrderId == null) {
            return error("订单不存在");
        }
        if (!StrUtil.equals(OrderStateEnum.ORDER_STATE_TO_BE_SIGNED.getValue(), orderByOrderId.getOrderState())) {
            return error("订单状态异常，修改失败");
        }
        order.setOrderState(orderByOrderId.getOrderState());
        IOrderStateServerRole orderStateServerRole = new OrderStateServerRole(order);
        orderStateServerRole.changeOrder();
        return success();

    }

    /**
     * 订单作废
     */
    @GetMapping("/cancel/{orderId}")
    @TenantScope
    public AjaxResult cancel(@PathVariable String orderId) {
        return orderService.cancel(orderId);
    }

    /**
     * 退租
     */
    @PostMapping("/refundRent")
    @TenantScope
    public AjaxResult refundRent(@RequestBody Order order) {
        if (ObjectUtil.isEmpty(order.getRealityCheckOutTime())) {
            return error("请输入退租日期");
        }
        Order orderByOrderId = orderService.selectOrderByOrderId(order.getOrderId());
        if (orderByOrderId == null) {
            return error("订单不存在");
        }
        orderByOrderId.setRealityCheckOutTime(order.getRealityCheckOutTime());
        orderService.refundRent(orderByOrderId);
        return success();
    }

    /**
     * 续租
     */
    @PostMapping("/relet")
    @TenantScope
    public AjaxResult relet(@RequestBody Order order) {
        Order orderByOrderId = orderService.selectOrderByOrderId(order.getOrderId());
        if (orderByOrderId == null) {
            return error("订单不存在");
        }
        order.setOrderState(orderByOrderId.getOrderState());
        orderService.relet(order);
        return success();
    }


    /**
     * 换房
     */
    @PostMapping("/exchangeHouse")
    @TenantScope
    public AjaxResult exchangeHouse(@RequestBody Order order) {
        Order orderByOrderId = orderService.selectOrderByOrderId(order.getOrderId());
        if (orderByOrderId == null) {
            return error("订单不存在");
        }
        order.setOrderState(orderByOrderId.getOrderState());
        orderService.exchangeHouse(order);
        return success();
    }

    /**
     * 转租
     */
    @PostMapping("/sublease")
    @TenantScope
    public AjaxResult sublease(@RequestBody Order order) {
        Order orderByOrderId = orderService.selectOrderByOrderId(order.getOrderId());
        if (orderByOrderId == null) {
            return error("订单不存在");
        }
        order.setOrderState(orderByOrderId.getOrderState());
        orderService.sublease(order);
        return success();
    }

    /**
     * 短租订单代入住->已入住
     */
    @PostMapping("/checkIn")
    @TenantScope
    @RepeatSubmit
    public AjaxResult checkIn(@RequestBody Order order) {
        Order byId = orderService.selectOrderById(order.getOrderId());
        if (!OrderStateEnum.ORDER_STATE_STAY_CHECK_IN.getValue().equals(byId.getOrderState())) {
            return error("订单状态异常，请刷新后再试");
        }
        if (order.getRealityCheckInTime().before(byId.getCheckInTime()) || order.getRealityCheckInTime().after(byId.getCheckOutTime())) {
            return error("入住时间超出当前订单预订范围");
        }
        //当前时间在入住时间之前
        if (DateUtils.getNowDate().before(byId.getCheckInTime())) {
            return error("未到入住日期，不能进行入住");
        }
        List<Order> orderList = orderService.selectOrderByHouseIdAndCheckIn(byId.getHouseId());
        if (CollectionUtil.isNotEmpty(orderList)) {
            return error("房间已有租客入住");
        }
        return toAjax(orderService.checkIn(order, OrderConstants.RECORD_SOURCE_ENTERPRISE, getUserId()));
    }

    /**
     * 短租订单代入住->取消预订
     */
    @PostMapping("/cancelReservation")
    @TenantScope
    @RepeatSubmit
    public AjaxResult cancelReservation(@RequestBody OrderStateRecord orderStateRecord) {
        Order byId = orderService.selectOrderById(orderStateRecord.getOrderId());
        if (!OrderStateEnum.ORDER_STATE_STAY_CHECK_IN.getValue().equals(byId.getOrderState())) {
            return error("订单状态异常，请刷新后再试");
        }
        orderStateRecord.setRecordSource(OrderConstants.RECORD_SOURCE_ENTERPRISE);
        return toAjax(orderService.cancelReservation(orderStateRecord, getUsername(), getUserId(), OrderConstants.AUDIT_SOURCE_ENTERPRISE));
    }

    /**
     * 短租订单代入住、已入住进行换房
     */
    @PostMapping("/apartment/exchangeHouse")
    @TenantScope
    @RepeatSubmit
    public AjaxResult apartmentExchangeHouse(@RequestBody Order order) {
        Order byId = orderService.selectOrderById(order.getOrderId());
        if (StrUtil.isBlank(order.getHouseId())) {
            return error("请选择换后房间");
        }
        if (byId.getHouseId().equals(order.getHouseId())) {
            return error("不可选择当前订单的房子");
        }
        if (!(OrderStateEnum.ORDER_STATE_STAY_CHECK_IN.getValue().equals(byId.getOrderState())
                || OrderStateEnum.ORDER_STATE_CHECK_IN.getValue().equals(byId.getOrderState()))) {
            return error("订单状态异常，请刷新后再试");
        }
        byId.setHouseId(order.getHouseId());
        if (orderService.checkRepeatOrder(byId)) {
            return error("换后房间在入离日期内已被预订");
        }
        if (orderService.checkLinkedOrderState(order.getOrderId())) {
            return error("房间有正在办理的续租业务，请处理后再试");
        }
        return toAjax(orderService.apartmentExchangeHouse(byId));
    }

    /**
     * 短租订单已入住订单--续租
     */
    @PostMapping("/apartment/relet")
    @TenantScope
    @RepeatSubmit
    public AjaxResult apartmentRelet(@RequestBody Order order) {
        if (ObjectUtil.isEmpty(order.getRentDay()) || order.getRentDay() <= 0) {
            return error("续租天数需大于0");
        }
        Order byId = orderService.selectOrderById(order.getOrderId());
        if (ObjectUtil.isEmpty(byId)) {
            return error("订单数据异常");
        }
        Date checkOutTime;
        String linkedOrderId;
        if (orderService.checkLinkedOrderState(order.getOrderId())) {
            return error("房间有正在办理的续租业务，请处理后再试");
        }
        if (StrUtil.isBlank(byId.getLinkedOrderId())) {
            if (!OrderStateEnum.ORDER_STATE_CHECK_IN.getValue().equals(byId.getOrderState())) {
                return error("订单状态异常，请刷新后再试");
            }
            linkedOrderId = byId.getOrderId();
        } else {
            Order parentOrder = orderService.selectOrderById(byId.getLinkedOrderId());
            if (!OrderStateEnum.ORDER_STATE_CHECK_IN.getValue().equals(parentOrder.getOrderState())) {
                return error("订单状态异常，请刷新后再试");
            }
            linkedOrderId = parentOrder.getOrderId();
        }
        Order linkedOrder = orderService.selectNewOrderByLinkedOrderId(linkedOrderId);
        if (ObjectUtil.isEmpty(linkedOrder)) {
            checkOutTime = byId.getCheckOutTime();
        } else {
            checkOutTime = linkedOrder.getCheckOutTime();
        }
        Date date = DateUtils.addDays(checkOutTime, order.getRentDay());
        Order newOrder = new Order();
        newOrder.setCheckInTime(checkOutTime);
        newOrder.setCheckOutTime(date);
        newOrder.setHouseId(byId.getHouseId());
        if (orderService.checkRepeatOrder(newOrder)) {
            return error("房间在入离日期内已被预订");
        }
        order.setCreateBy(getUsername());
        if (!StrUtil.equals(linkedOrderId, order.getOrderId())) {
            order.setLinkedOrderId(linkedOrderId);
        }
        return toAjax(orderService.apartmentRelet(order));
    }

    /**
     * 查看退房中退房金额详细信息
     */
    @GetMapping("/apartment/checkingOut/{orderId}")
    public AjaxResult apartmentCheckingOutInfo(@PathVariable String orderId) {
        Order byOrderId = orderService.selectOrderById(orderId);
        if (ObjectUtil.isEmpty(byOrderId)) {
            return error("订单数据异常");
        }
        List<Order> orderList = orderService.selectOrderByLinkedOrderId(orderId);
        if (CollectionUtil.isNotEmpty(orderList)) {
            byOrderId.setCheckOutTime(orderList.get(orderList.size() - 1).getCheckOutTime());
        }
        if (!(OrderStateEnum.ORDER_STATE_CHECKING_OUT.getValue().equals(byOrderId.getOrderState()) ||
                OrderStateEnum.ORDER_STATE_COMPLETED.getValue().equals(byOrderId.getOrderState()))) {
            return error("订单状态异常，请刷新后再试");
        }
        return success(orderService.apartmentCheckingOutInfo(orderId));
    }

    /**
     * 短租订单已入住订单--退房中
     */
    @PostMapping("/apartment/checkingOut")
    @TenantScope
    @RepeatSubmit
    public AjaxResult apartmentCheckingOut(@RequestBody Order order) {
        if (StrUtil.equals(order.getChargeType(), "1") && order.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0) {
            return error("收费金额需大于0元");
        }
        Order byId = orderService.selectOrderById(order.getOrderId());
        if (ObjectUtil.isEmpty(byId)) {
            return error("订单数据异常");
        }
        if (StrUtil.isBlank(byId.getLinkedOrderId())) {
            if (!OrderStateEnum.ORDER_STATE_CHECK_IN.getValue().equals(byId.getOrderState())) {
                return error("订单状态异常，请刷新后再试");
            }
        } else {
            return error("续租订单不可操作退房业务，请去父订单操作");
        }

        //退房时间在入住时间之前
        if (order.getRealityCheckOutTime().before(byId.getCheckInTime())) {
            return error("退房时间不能早于入住时间");
        }

        if (orderService.checkLinkedOrderState(order.getOrderId())) {
            return error("房间有正在办理的续租业务，请处理后再试");
        }
        order.setCreateBy(getUsername());
        order.setOperatorId(getUserId());
        return toAjax(orderService.apartmentCheckingOut(order));
    }

    /**
     * 短租订单退房订单--已完成（退费处理）
     */
    @PostMapping("/apartment/completed")
    @TenantScope
    @RepeatSubmit
    public AjaxResult apartmentCompleted(@RequestBody Order order) {
        Order byId = orderService.selectOrderById(order.getOrderId());
        if (ObjectUtil.isEmpty(byId)) {
            return error("订单数据异常");
        }
        if (StrUtil.isBlank(byId.getLinkedOrderId())) {
            if (!OrderStateEnum.ORDER_STATE_CHECKING_OUT.getValue().equals(byId.getOrderState())) {
                return error("订单状态异常，请刷新后再试");
            }
        } else {
            return error("续租订单不可操作退房业务，请去父订单操作");
        }

        if (orderService.checkLinkedOrderState(order.getOrderId())) {
            return error("房间有正在办理的续租业务，请处理后再试");
        }
        order.setCreateBy(getUsername());
        order.setOperatorId(getUserId());
        return orderService.apartmentCompleted(order);
    }

    /**
     * 可新增账单订单列表
     */
    @GetMapping("/addBillList")
    @TenantScope
    public TableDataInfo addBillList(Order order) {
        startPage();
        order.setTenantId(TenantContext.getTenantId());
        List<Order> list = orderService.selectAddBillList(order);
        return getDataTable(list);
    }
}
